/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
/* -------------------------------------------------------------------------------------------------*/
/* File Name:                                                                                      */
/*    VPOST_Demo_NOSD.c                                                                            */
/* Description:                                                                                    */
/*     LCD display controller test program                                                                      */
/* History:                                                                                        */
/*                                                                                                 */
/* Project:                                                                                        */
/*-------------------------------------------------------------------------------------------------*/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"

#include "NUC900_vpost.h"
//#include "NUC900_VPOST_Regs.h"
#include "NUC900_reg.h"

#define USEUART 1
#define AUO_A035QN02_950 1
//#define CACHE_ON 0    // cache on/off
//#define TV_ENCODE 0
#define NORMAL_MODE 1
//#define MPU_TYPE
//#define SYNC_TYPE


#define SYSCLK 15000000

#define get_timer_ticks()	sysGetTicks(TIMER0)

#if USEUART
#undef getchar
#define getchar		sysGetChar
#define printf		sysprintf
#endif// end of #if USEUART


const UINT8 ScreenBitmap[] = {
    #include "PACKET_RGB565_size320x240_CCU.dat"
    //#include "images320x240_RGB666_size320x240_0RGB.dat"
    //#include "Packet_RGB565_size1024x768_ascii.dat"
    //#include "melissa_RGB444_size240x320_Ascii.dat"
    //#include "melissa_RGB565_size240x320_Ascii.dat"
    //#include "melissa_RGB666_size240x320_Ascii.dat"
    //#include "melissa_RGB888_size240x320_Ascii.dat"
    //#include "Rolvaag_YUV422_size720x484_Ascii.dat"
    //#include "Rolvaag_YUV422_size720x242_ascii.dat"
    //#include "packet_RGB444_size128x160_ascii.dat"
    //#include "packet_RGB565_size128x160_ascii.dat"
    //#include "packet_RGB666_size128x160_ascii.dat"
    //#include "packet_RGB888_size128x160_ascii.dat"
};



__align(32) UINT8 _ucOSD_buff[]=
{
	  #include "BAR_RGB565.dat"
//    #include "BAR_YUV422.dat"
//    #include "BAR_YCBCR422.dat"
//    #include "BAR_RGB888.dat"
//    #include "BAR_RGB666.dat"
//    #include "BAR_RGB444H.dat"
//    #include "BAR_RGB444L.dat"
};



__align(32) UINT32 uaCursorBuf[512];
VOID lcd_test(VOID);

//#define NUC900_DIAG

#ifndef NUC900_DIAG
VOID _InitSystem(VOID)
{

    WB_PLL_T sysClock;
    WB_UART_T uart;

	#if CACHE_ON
    sysDisableCache();
    sysInvalidCache();
    sysSetMMUMappingMethod(MMU_DIRECT_MAPPING);
    sysEnableCache(CACHE_WRITE_BACK);
    printf("Cache on!!!\n");
	#endif
	
	#if NORMAL_MODE
    sysClock.pll0 = PLL_200MHZ;
    sysClock.pll1 = PLL_100MHZ;
    sysClock.cpu_src = CPU_FROM_PLL0;
    sysClock.ahb_clk = AHB_CPUCLK_1_2;
    sysClock.apb_clk = APB_AHB_1_2;
    sysSetPLLConfig(&sysClock);
      
    outpw(0xB0000204, inpw(0xB0000204) & ~0xC0);  // clear video clock
	outpw(0xB0000204, inpw(0xB0000204) | 0x40);   // video clock select PLL1
	outpw(0xB0000208, inpw(0xB0000208) & ~0xf000 | 0xd000);  // video clock div 14
    
    #endif
    
    #if AUO_A035QN02_950
    sysClock.pll0 = PLL_200MHZ;
    sysClock.pll1 = PLL_66MHZ;
    sysClock.cpu_src = CPU_FROM_PLL0;
    sysClock.ahb_clk = AHB_CPUCLK_1_2;
    sysClock.apb_clk = APB_AHB_1_2;
    sysSetPLLConfig(&sysClock);
      
    outpw(0xB0000204, inpw(0xB0000204) & ~0xC0);  // clear video clock
	outpw(0xB0000204, inpw(0xB0000204) | 0xC0);   // video clock select ext15M
	outpw(0xB0000208, inpw(0xB0000208) & ~0xf000 | 0x2000);  // video clock div 3
    
    #endif
    
    #if TV_ENCODE
    sysClock.pll0 = PLL_166MHZ;
    sysClock.pll1 = 0x3563;     // 81MHz
    sysClock.cpu_src = CPU_FROM_PLL1;
    sysClock.ahb_clk = AHB_CPUCLK_1_2;
    sysClock.apb_clk = APB_AHB_1_2;
    sysSetPLLConfig(&sysClock);
    #endif
    
    #if 0
	uart.uiFreq = SYSCLK;
    uart.uiBaudrate = 115200;
    uart.uiDataBits = WB_DATA_BITS_8;
    uart.uiStopBits = WB_STOP_BITS_1;
    uart.uiParity = WB_PARITY_NONE;
    uart.uiRxTriggerLevel = LEVEL_1_BYTE;
    sysInitializeUART(&uart);
    outpw(REG_MFSEL,inpw(REG_MFSEL) | 0x1f00);
	
	
    sysSetTimerReferenceClock(TIMER0,SYSCLK);
	sysStartTimer(TIMER0,100,PERIODIC_MODE);
	#endif
	
	#if TV_ENCODE
	outpw(0xB0000204, inpw(0xB0000200) & ~0xC0);  // clear video clock
	outpw(0xB0000204, inpw(0xB0000200) | 0x40);   // video clock select PLL1
	outpw(0xB0000208, inpw(0xB0000208) & ~0xf000 | 0x2000);  // video clock div 3
	#endif

}
#endif

#ifdef NUC900_DIAG
INT diag_lcd(VOID)
#else
INT main(VOID)
#endif
{
	
	
#ifndef NUC900_DIAG
    _InitSystem();
#endif

	





/* ----------Video Initialization (Display_Continus)-----------------  */    

	//vpostVASetDisplayBuff(0x40000,0x80000);//dual buffer

	
	
	
	lcd_test();
	
	
    return 0;
}

VOID HWCursorTest()
{
    UINT32 i;
    UINT8 choose;
    //UINT32 uShiftCount=0x2;
    UINT32 uShiftCount=0x4;   // modify by smf
    INT32	uHCX=0,uHCY=0;
    UINT32 ScreenW,ScreenH;
    ScreenW=1024;
    ScreenH=768;
    
    printf("************ User's Guide for HWCursorTest ************\n");
	printf("Describtion:Press 'w' for moving up the cursor\n");
	printf("            Press 's' for moving down the cursor\n");
	printf("            Press 'a' for moving left the cursor\n");
	printf("            Press 'd' for moving right the cursor\n");
	printf("            Press 'z' for exiting the test\n");
	printf("************                             ************\n");
    
    for (i=0;i<16;i++)
    {
    	uaCursorBuf[i] = 0x00;
        uaCursorBuf[i+16*1] = 0x55555555;
        uaCursorBuf[i+16*2] = 0xaaaaaaaa;
        uaCursorBuf[i+16*3] = 0xffffffff;
        uaCursorBuf[i+16*4] = 0x00;
        uaCursorBuf[i+16*5] = 0x55555555;
        uaCursorBuf[i+16*6] = 0xaaaaaaaa;
        uaCursorBuf[i+16*7] = 0xffffffff;
        uaCursorBuf[i+16*8] = 0x00;
        uaCursorBuf[i+16*9] = 0x55555555;
        uaCursorBuf[i+16*10] = 0xaaaaaaaa;
        uaCursorBuf[i+16*11] = 0xffffffff;
        uaCursorBuf[i+16*12] = 0x00;
        uaCursorBuf[i+16*13] = 0x55555555;
        uaCursorBuf[i+16*14] = 0xaaaaaaaa;
        uaCursorBuf[i+16*15] = 0xffffffff;
        uaCursorBuf[i+16*16] = 0x00;
        uaCursorBuf[i+16*17] = 0x55555555;
        uaCursorBuf[i+16*18] = 0xaaaaaaaa;
        uaCursorBuf[i+16*19] = 0xffffffff;
        uaCursorBuf[i+16*20] = 0x00;
        uaCursorBuf[i+16*21] = 0x55555555;
        uaCursorBuf[i+16*22] = 0xaaaaaaaa;
        uaCursorBuf[i+16*23] = 0xffffffff;
        uaCursorBuf[i+16*24] = 0x00;
        uaCursorBuf[i+16*25] = 0x55555555;
        uaCursorBuf[i+16*26] = 0xaaaaaaaa;
        uaCursorBuf[i+16*27] = 0xffffffff;
        uaCursorBuf[i+16*28] = 0x00;
        uaCursorBuf[i+16*29] = 0x55555555;
        uaCursorBuf[i+16*30] = 0xaaaaaaaa;
        uaCursorBuf[i+16*31] = 0xffffffff;
    }
    
    vpostHCInit(uaCursorBuf,HC_MODE0);
    
    do{
        choose = getchar();
        //printf("%d\n",choose);
        switch (choose)
        {
            
            case 'w':
                uHCY = uHCY - uShiftCount;
                if (uHCY<0)
                    uHCY=0;
                vpostHCPosCtrl(uHCX,uHCY);
                
                break;
            case 's':
                uHCY = uHCY + uShiftCount;
                if (uHCY>ScreenH)
                    uHCY=ScreenH-1;
                vpostHCPosCtrl(uHCX,uHCY);
                break;
            case 'a':
                uHCX = uHCX - uShiftCount;
                if (uHCX<0)
                    uHCX=0;
                vpostHCPosCtrl(uHCX,uHCY);
                break;
            case 'd':
                uHCX = uHCX + uShiftCount;
                if (uHCX>ScreenW)
                    uHCX=ScreenW-1;
                vpostHCPosCtrl(uHCX,uHCY);
                break;
            case 'z':
            return;
            default:
            break;
        }
    }while(1);
}
VOID HR_HSYNC_VR_Test(void)
{
    UINT32 VR_S, VR_E, HR_S, HR_E, HSYNC_S, HSYNC_E;
    UINT8 choose;
   
    printf("************ User's Guide for HWCursorTest ************\n");
	printf("Describtion:Press 'w' for VR_S\n");
	printf("            Press 's' for VR_E\n");
	printf("            Press 'a' for HR_S & HSYNC_S\n");
	printf("            Press 'd' for HR_E & HSYNC_E\n");
	printf("            Press 'z' for exiting the test\n");
	printf("************                             ************\n");
   
    VR_S=0x313;
    VR_E=0x315;
    HR_S=0x470;
    HR_E=0x480;
    HSYNC_S=0x470;
    HSYNC_E=0x480;
    //vpostHCInit(uaCursorBuf,HC_MODE0);
    
    do{
        choose = getchar();
        //printf("%d\n",choose);
        switch (choose)
        {
            //input = 0x00;
            case 'w':
            	VR_S+=1;
                printf("VR_S : %x", VR_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) & ~0x7ff);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) | VR_S);
                
                break;
            case 's':
            	VR_S-=1;
                printf("VR_S : %x", VR_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) & ~0x7ff);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) | VR_S);
                
                break;
            case 'a':
	            VR_E-=1;
                printf("Input VR_E : %x", VR_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) & ~(0x7ff<<16));
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) | VR_E<<16);
                
                break;
            case 'd':
	            VR_E+=1;
                printf("Input VR_E : %x", VR_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) & ~(0x7ff<<16));
                outpw(REG_LCM_CRTC_VR, inpw(REG_LCM_CRTC_VR) | VR_E<<16);
                
                break;
            case 'i':
            	HR_S+=1;
                printf("Input HR_S&HSYNC_S : %x", HR_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) & ~0x7ff);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) | HR_S);
                
                break;
            case 'k':
            	HR_S-=1;
                printf("Input HR_S&HSYNC_S : %x", HR_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) & ~0x7ff);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) | HR_S);
                
                break;
            case 'j':
            	HR_E-=1;
                printf("Input HR_E&HSYNC_E : %x", HR_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) & ~(0x7ff<<16));
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) | HR_E<<16);
                
                break;
            case 'l':
            	HR_E+=1;
                printf("Input HR_E&HSYNC_E : %x", HR_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) & ~(0x7ff<<16));
                outpw(REG_LCM_CRTC_HR, inpw(REG_LCM_CRTC_HR) | HR_E<<16);
                
                break;
            case 't':
            	HSYNC_S+=1;
                printf("Input HSYNC_S : %x", HSYNC_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) & ~0x7ff);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) | HSYNC_S);
                
                break;
            case 'g':
            	HSYNC_S-=1;
                printf("Input HSYNC_S : %x", HSYNC_S);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) & ~0x7ff);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) | HSYNC_S);
                
                break;
            case 'f':
            	HSYNC_E-=1;
                printf("Input HSYNC_E : %x", HSYNC_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) & ~0x7ff);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) | HSYNC_E<<16);
                
                break;
            case 'h':
            	HSYNC_E+=1;
                printf("Input HSYNC_E : %x", HSYNC_E);
                //scanf("%x",&input);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) & ~0x7ff);
                outpw(REG_LCM_CRTC_HSYNC, inpw(REG_LCM_CRTC_HSYNC) | HSYNC_E<<16);
                
                break;
            case 'z':
            return;
            default:
            break;
        }
    }while(1);
}
VOID convertRGB(UINT32 *framebuf, UINT32 FrameBufferSize, UINT32 format)
{
	UINT idx;
	UINT8 *ptr_RGB;
	UINT32 *ptr32, r32, g32, b32;
	UINT32 g32_1, g32_2, r32_1, r32_2;
	
	ptr_RGB = (UINT8 *)framebuf;
	if(format == VA_SRC_RGB666)
	{
		ptr32 = (UINT32 *)framebuf;
		//printf("frambuf %x, buffer size %x\n", framebuf, FrameBufferSize);
		//printf("ptr_RGB is %x\n", *ptr_RGB);
		
		for(idx = 0; idx < FrameBufferSize; idx++)
		{
			b32 = (UINT8)(*ptr_RGB) & 0x3f;
			g32_1 = (UINT8)(*ptr_RGB++) & 0xc0;
			g32_2 = (UINT8)(*ptr_RGB) & 0xf;
			g32 = g32_2<<2 | g32_1>>6;
			r32_1 = (UINT8)(*ptr_RGB++) & 0xf0;
			r32_2 = (UINT8)(*ptr_RGB) & 0x3;
			r32 = r32_1>>4 | r32_2<<4;
			ptr_RGB+=2;
			
			*ptr32 = 0x0;
			*ptr32++ = (r32 << 18) | (g32 << 10) | (b32 <<2);
			//printf("ptr32 is %x\n", *ptr32);
		}
		
	} else {
		printf("VA Source is not RGB666\n");
	}
}
VOID ScalingControl(VOID)
{
	int scaleindex = 1;
	printf("Vertical & Horizontal Up 1~7.99999\n");
	for(scaleindex=1; scaleindex<=7; scaleindex++)
	{
		vpostVAScalingCtrl(1,scaleindex,1,scaleindex,VA_SCALE_INTERPOLATION);
		getchar();
	}

}
VOID lcd_test()
{
    UINT32 uCKey,uCMask;
    UINT8 ucWeight;
    //UINT32	uOSDSrcFormat;
    int item=0;
    int count=10000;
    int	choose;
	CHAR TestItems[6]={'1','2','3','4','9','z'};
	//CHAR TestItems[3]={'1','5','z'};
	LCDFORMATEX lcdformatex;
	OSDFORMATEX osdformatex;
	UINT32 *pframbuf=NULL;
	printf("************ User's Guide for LCD Demo ************\n");
	printf("Describtion:This demo program work with TD035TTEA3\n");
	printf("            on the NUC900 EV board.\n");
	printf("            There will be 5 tests for Video and OSD\n");
	printf("    Setting:1. LCD module TD035TTEA3 is required\n");
	printf("     Result:OK, if show the image normally\n");
    printf("            Fail, can't show the image normally\n");
	printf("************                             ************\n");
	sysprintf("\n\nPress any key to start...\n");
	sysGetChar();
    printf("LCM test\n");
    do{
		
		int STicks=0;
		
		//uOSDSrcFormat = OSD_SRC_RGB565;
		
		printf("=======================================\n");
		printf("1.Video Display test\n");
		printf("2.OSD Display test\n");
		printf("3.OSD transparent test\n");
		printf("4.OSD blinking test\n");
		printf("5.Tranfer RGB666 source format\n");
		printf("6.Scaling Control\n");
		printf("9.Hardware Cursor test\n");
		printf("z.Exit\n");
		printf("select:");

		//gets(&choose);
		//scanf("%c\n",choose);
				
        choose = getchar();
        //choose = TestItems[item++];
		printf("Test Item %c\n",choose);
        
		switch(choose)
		{
			case '1':
				lcdformatex.ucVASrcFormat = VA_SRC_RGB565;
		
                vpostLCMInit(&lcdformatex);
                pframbuf = vpostGetFrameBuffer();
                                               
                if (pframbuf==NULL)
                    printf("NULL FRAME BUFFER\n");
                else {
                	vpostClearVABuffer();
                    memcpy(pframbuf,ScreenBitmap,sizeof(ScreenBitmap));
                }
				break;
			case '2':
				osdformatex.ucOSDSrcFormat = OSD_SRC_RGB565;
                osdformatex.nXstart = 50;
                osdformatex.nYstart = 50;
                osdformatex.nOSDWidth = 128;
                osdformatex.nOSDHeight = 160;
                osdformatex.nImageWidth = 128;
                //osdformatex.nOSDWidth = 32;
                //osdformatex.nOSDHeight = 40;
                //osdformatex.nImageWidth = 32;
                osdformatex.pFrameBuffer = (PUINT32)_ucOSD_buff;
                vpostOSDInit(&osdformatex);
				break;
			case '3':
			
				if (osdformatex.ucOSDSrcFormat == OSD_SRC_RGB565)
				{
					uCKey = 0x00f80000;//key=R
					uCMask = 0x00f8fcf8;//RGB565
				}
				ucWeight = 4;
				vpostOSDSetOverlay(DISPLAY_SYNTHESIZED,DISPLAY_OSD,uCKey,uCMask,ucWeight);
				
			break;
			case '4':
			    vpostOSDSetBlinking(5);
			break;
			case '5':
				convertRGB(pframbuf, lcdformatex.nFrameBufferSize, VA_SRC_RGB666);  // add by smf
			break;
			case '6':
			 	ScalingControl();
				
			break;
			case '7':
				HR_HSYNC_VR_Test();
			break;
			case '9':
			    HWCursorTest();
			break;
			break;
			case 'z':
			    vpostLCMDeinit();
			return;
			default:break;
			
			
		}
		//STicks = get_timer_ticks();
		//while((get_timer_ticks() - STicks) < 300);//delay 5 sec
		while(count>0) { count--;}
	}while(1);
}


#ifndef NUC900_DIAG

/*
 * standalone.c - minimal bootstrap for C library
 * Copyright (C) 2000 ARM Limited.
 * All rights reserved.
 */

/*
 * RCS $Revision: 1 $
 * Checkin $Date: 08/08/22 10:00p $ 0
 * Revising $Author: Mncheng $
 */

/*
 * This code defines a run-time environment for the C library.
 * Without this, the C startup code will attempt to use semi-hosting
 * calls to get environment information.
 */
#include <rt_misc.h>

__value_in_regs struct __initial_stackheap __user_initial_stackheap(
	unsigned R0, unsigned SP, unsigned R2, unsigned SL)
{
	struct __initial_stackheap config;
	config.heap_base = 0x00440000;
	config.heap_limit = 0x500000;
	config.stack_base = 0x600000;
	config.stack_limit = 0x500000;
	return config;
}
void _sys_exit(int return_code)
{
label:  goto label; /* endless loop */
}

void _ttywrch(int ch)
{
    char tempch = (char)ch;
    (void)tempch;
}
/* end of file standalone.c */

/* end of file standalone.c */
#endif